package tianrun.ziguan.api.calculate.config.utils;

import tianrun.ziguan.api.calculate.config.constant.StringPools;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Objects;

/**
 * 时间工具类
 */
public class DateUtil {

    private DateUtil() {
    }

    public static final String TIME_PATTERN = "yyyy年MM月dd日 HH:mm";

    public static final String TIME_UNIT_PATTERN = "yyyy年MM月dd日HH时mm分";

    public static final String FULL_TIME_SPLIT_PATTERN = "yyyy-MM-dd HH:mm:ss";

    public static final String FULL_TIME_TIME_DIVISION = "yyyy-MM-dd HH:mm";

    public static final String DATE_TIME_PATTERN = "yyyy-MM-dd";

    public static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_TIME_PATTERN);

    public static final ZoneId ZONE_ID = ZoneId.of("Asia/Shanghai");

    public static String formatFullTime(LocalDateTime localDateTime) {
        return formatFullTime(localDateTime, TIME_PATTERN);
    }

    public static String formatFullTime(LocalDateTime localDateTime, String pattern) {
        if (Objects.isNull(localDateTime)) {
            return StringPools.EMPTY;
        }
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
        return localDateTime.format(dateTimeFormatter);
    }

    public static Long parseLong(LocalDateTime time) {
        if (time == null) {
            return null;
        }
        return time.atZone(ZONE_ID).toInstant().toEpochMilli();
    }

    public static Long parseLong(String time) {
        if (time == null) {
            return null;
        }
        try {
            return parseLong(LocalDateTime.parse(time, DateTimeFormatter.ofPattern(FULL_TIME_SPLIT_PATTERN)));
        } catch (Exception ignored) {
        }
        return Long.valueOf(time);
    }

    public static LocalDateTime parseLocalDateTimeByDate(String date) {
        if (date == null) {
            return null;
        }
        return LocalDate.parse(date, DateTimeFormatter.ofPattern(DATE_TIME_PATTERN)).atStartOfDay();
    }

    public static LocalDateTime parseLocalDateTime(String time) {
        if (time == null) {
            return null;
        }
        return LocalDateTime.parse(time, DateTimeFormatter.ofPattern(FULL_TIME_SPLIT_PATTERN));
    }

    public static LocalDateTime parseLocalDateTime(Long time) {
        if (time == null) {
            return null;
        }
        return Instant.ofEpochMilli(time).atZone(ZONE_ID).toLocalDateTime();
    }

    public static String parseTimeStr(Long time) {
        if (time == null) {
            return null;
        }
        return Instant.ofEpochMilli(time).atZone(ZONE_ID).toLocalDateTime().format(DateTimeFormatter.ofPattern(FULL_TIME_SPLIT_PATTERN));
    }

    public static String parseTimeStr(Long time, DateTimeFormatter dateTimeFormatter) {
        if (time == null) {
            return null;
        }
        return Instant.ofEpochMilli(time).atZone(ZONE_ID).toLocalDateTime().format(dateTimeFormatter);
    }

    public static String parseTimeStr(LocalDateTime time) {
        if (time == null) {
            return null;
        }
        return time.format(DateTimeFormatter.ofPattern(FULL_TIME_SPLIT_PATTERN));
    }

    public static String parseTimeDivisionStr(LocalDateTime time) {
        if (time == null) {
            return null;
        }
        return time.format(DateTimeFormatter.ofPattern(FULL_TIME_TIME_DIVISION));
    }


    public static LocalDateTime now(String zone) {
        ZoneId zoneId;
        if (StringUtil.isEmpty(zone)) {
            zoneId = ZoneId.of("UTC+8");
        } else {
            zoneId = ZoneId.of(zone);
        }
        return LocalDateTime.now(zoneId);
    }

    public static LocalDateTime nowAsiaShanghai() {
        return LocalDateTime.now(ZONE_ID);
    }

    public static String timeStringByFormat(LocalDateTime time, String format) {
        if (Objects.isNull(time)) {
            return null;
        }
        if (StringUtil.isBlank(format)) {
            format = FULL_TIME_SPLIT_PATTERN;
        }
        return time.format(DateTimeFormatter.ofPattern(format));
    }

    public static String nowTimeStr() {
        return nowAsiaShanghai().format(DateTimeFormatter.ofPattern(FULL_TIME_SPLIT_PATTERN));
    }

    public static ZonedDateTime utcStrToZonedDateTime(String utcTimeStr) {
        Instant instant = Instant.parse(utcTimeStr);
        return ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
    }

    public static LocalDateTime utcStrToLocalDateTime(String utc) {
        return utcStrToZonedDateTime(utc).toLocalDateTime();
    }

    public static Long utcStrToLong(String utc) {
        return utcStrToLocalDateTime(utc).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    public static String strLongToUtcStr(String time) {
        return longToUtcStr(Long.parseLong(time));
    }

    public static String longToUtcStr(Long time) {
        return Instant.ofEpochMilli(time).toString();
    }


    public static String toString(LocalDateTime o) {
        return parseTimeStr(o);
    }

    public static String toString(Timestamp o) {
        return toString(o.toLocalDateTime());
    }

    public static String toString(Long o) {
        return toString(parseLocalDateTime(o));
    }

    public static LocalDateTime getCurrentDateTimeDiff(Long val) {
        return LocalDateTime.now().plusSeconds(val);
    }

    public static LocalDateTime atStartOfDay(Long timestamp) {
        if (timestamp == null) {
            return null;
        }
        YearMonth yearMonth = ofYearMonth(timestamp);
        LocalDate localDate = yearMonth.atDay(1);
        return localDate.atStartOfDay();
    }

    public static LocalDateTime atStartOfDay(LocalDateTime localDateTime) {
        return atStartOfDay(DateUtil.parseLong(localDateTime));
    }

    public static LocalDateTime endOfMonth(Long timestamp) {
        if (timestamp == null) {
            return null;
        }
        YearMonth yearMonth = ofYearMonth(timestamp);
        LocalDate endOfMonth = yearMonth.atEndOfMonth();
        return endOfMonth.atTime(23, 59, 59, 999999999);

    }

    public static LocalDateTime endOfMonth(LocalDateTime localDateTime) {
        return endOfMonth(DateUtil.parseLong(localDateTime));

    }

    public static YearMonth ofYearMonth(Long timestamp) {
        LocalDateTime localDateTime = DateUtil.parseLocalDateTime(timestamp);
        return YearMonth.of(localDateTime.getYear(), localDateTime.getMonth());
    }

    public static LocalDateTime getBeforeOneDay(LocalDateTime time, int judge) {
        LocalDateTime yesterday = time.minusDays(1);
        if (1 == judge) {
            return yesterday.toLocalDate().atStartOfDay();
        } else if (0 == judge) {
            return yesterday.toLocalDate().atTime(LocalTime.MAX);
        } else {
            return null;
        }
    }

    public static Boolean isSameDay(LocalDateTime startTime, LocalDateTime endTime) {
        if (startTime == null || endTime == null) {
            return false;
        }
        String startFormat = startTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        String endFormat = endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        return startFormat.equals(endFormat);
    }

}
